#include "RegistroDisco.h"

RegistroDisco::RegistroDisco(TipoMemoria tipo, int tamanio, FILE* fp){
	this->tipoMemoria = tipo;
	this->tamanio = tamanio;
	this->fp = fp;
	this->offset = ftell(this->fp);
	this->dato = NULL;
}

RegistroDisco::RegistroDisco(TipoMemoria tipo, int tamanio, FILE* fp, Dato *dato){
	this->tipoMemoria = tipo;
	this->tamanio = tamanio;
	this->fp = fp;
	this->offset = ftell(this->fp);
	this->dato = dato;
}

void RegistroDisco::getAccesoDato(void **accesoDato){
	fseek(this->fp,this->offset,SEEK_SET);
	*accesoDato = (void*) this->fp; 
}

void RegistroDisco::leer(Dato *datoLeido, TipoSerializacion modo){
	if(this->fp==NULL)
		throw new NullPointerException();
	unsigned int bytesLeidos;
	void *miDato = NULL;
	int bytesDato = this->tamanio;
	fseek(fp,this->offset,SEEK_SET);
	if(this->tipoMemoria!=FIJA){
		bytesLeidos = fread(&bytesDato, RegistroDisco::bytesControlTamanio, 1, fp);
		//if(bytesLeidos != RegistroDisco::bytesControlTamanio)
		if(!bytesLeidos)
			throw new DiscStorageException(StorageException::lectura);
	}	
	miDato = malloc(bytesDato);
	bytesLeidos = fread(miDato, bytesDato, 1, fp);	
	//if(bytesLeidos != this->tamanio)	
	if(!bytesLeidos)
		throw new DiscStorageException(StorageException::lectura);
	this->tamanio = bytesDato;
	if(this->tipoMemoria!=FIJA)
		this->tamanio += Registro::bytesControlTamanio;
	datoLeido->unserialize(miDato, modo);
	free(miDato);
}

void RegistroDisco::escribir(void *accesoDisco, TipoSerializacion modo){
	if(this->fp==NULL||accesoDisco==NULL)
		throw new NullPointerException();
	FILE *aux = (FILE*) accesoDisco;
	this->offset = ftell(aux);
	this->escribirEnDisco(modo);
}

void RegistroDisco::escribir(TipoSerializacion modo){
	if(this->fp==NULL)
		throw new NullPointerException();
	this->escribirEnDisco(modo);
}

void RegistroDisco::escribir(void *accesoDisco, Dato *dato, TipoSerializacion modo){
	if(this->fp==NULL||accesoDisco==NULL)
		throw new NullPointerException();
	this->dato = dato;
	FILE *aux = (FILE*) accesoDisco;
		this->offset = ftell(aux);
	this->tamanio = this->dato->getTamanio(modo) + Registro::bytesControlTamanio;
	this->escribirEnDisco(modo);
}

void RegistroDisco::borrar(){	
	if(this->fp==NULL)
		throw new NullPointerException();
	free(this->dato);
	this->dato = NULL;
}

void RegistroDisco::escribirEnDisco(TipoSerializacion modo){
	unsigned int bytesEscritos;
	fseek(this->fp,this->offset,SEEK_SET);
	if(this->tipoMemoria!=FIJA){
		int datosAEscribir = this->dato->getTamanio(modo);
		bytesEscritos = fwrite(&datosAEscribir, Registro::bytesControlTamanio, 1, fp);
		//if(bytesEscritos != Registro::bytesControlTamanio)
		if(!bytesEscritos)
			throw new DiscStorageException(StorageException::escritura);
	}
	void *datoAEscribir;
	datoAEscribir = malloc(this->dato->getTamanio(modo));
	this->dato->serialize(&datoAEscribir, modo);
	bytesEscritos = fwrite(datoAEscribir, this->dato->getTamanio(modo), 1, fp);
	//if(bytesEscritos != dato->getTamanio())
	if(!bytesEscritos)
			throw new DiscStorageException(StorageException::escritura);
	free(datoAEscribir);
}
